﻿using AutoStar.Common;
using AutoStar.ViewModel;
using GalaSoft.MvvmLight.CommandWpf;
using SharpGL;
using SharpGL.WPF;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;
using static AutoStar.Models.PrintSliceModel;
using static System.Windows.Forms.LinkLabel;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
using Application = System.Windows.Application;
using Model3D = AutoStar.Common.Model3D;
using Point3D = AutoStar.Common.Point3D;

namespace AutoStar.Views.Pages
{
    /// <summary>
    /// CurrentProjectView.xaml 的交互逻辑
    /// </summary>
    public partial class CurrentProjectView : Page
    {
        private CurrentProjectVM VM = Global.CurrentProjectVM;
        //private MainWindowVM _mainVM;
        public CurrentProjectView()
        {
            InitializeComponent();
            this.FontSize = 12;
            DataContext = VM;
            //Global.printProject = new PrintProject();
            openGLControl2.OpenGLDraw += OpenGLControl2_Loaded;
            openGLControl2.OpenGLInitialized += OpenGLControl2_OpenGLInitialized;
        }
        #region OpenGLContro事件

        /// <summary>
        /// OpenGLContro初始化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OpenGLControl2_OpenGLInitialized(object sender, OpenGLRoutedEventArgs args)
        {
            OpenGL gl = openGLControl2.OpenGL;
            gl.ClearColor(0.8f, 0.8f, 0.8f, 0.0f);
            //gl.Enable(OpenGL.GL_BLEND);
            //gl.BlendFunc(OpenGL.GL_SRC_ALPHA, OpenGL.GL_ONE_MINUS_SRC_ALPHA);
        }
        int look2 = 150;
        private double rotation2;

        //public static Global.printProject Global.printProject;//打印项目
        //public static Global.printer Global.printer = Global.printer.GetGlobal.printer(150, 130, 100);//打印机
        //public static Global.printer Global.printer = Global.Global.printer;//打印机
        //public static Global.printProject Global.printProject = Global.Global.printProject;//打印项目
        /// <summary>
        /// OpenGLContro绘制
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OpenGLControl2_Loaded(object sender, OpenGLRoutedEventArgs args)
        {
            OpenGL gl = openGLControl2.OpenGL;

            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

            gl.MatrixMode(OpenGL.GL_PROJECTION);
            gl.LoadIdentity();
            gl.Perspective(60.0f, (double)openGLControl2.ActualWidth / (double)openGLControl2.ActualHeight, 0.01, 500.0);
            gl.LookAt(look2, look2, look2, 0, 0, 0, 0, 0, 1);
            gl.MatrixMode(OpenGL.GL_MODELVIEW);

            gl.LoadIdentity();
            gl.Rotate(rotation2, 0.0f, 0.0f, 1.0f);
            gl.Begin(OpenGL.GL_LINES);
            gl.Color(0.0f, 0.0f, 0.0f);
            gl.Vertex(0.0f, 0.0f, 0.0f);
            gl.Vertex(400.0f, 0.0f, 0.0f);
            gl.Vertex(0.0f, 0.0f, 0.0f);
            gl.Vertex(0.0f, 400.0f, 0.0f);
            gl.Vertex(0.0f, 0.0f, 0.0f);
            gl.Vertex(0.0f, 0.0f, 400.0f);

            gl.Color(1.0f, 0.0f, 0.0f);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, 0);
            gl.Vertex(Global.printer.maxX, 0, 0);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, 0);
            gl.Vertex(0, Global.printer.maxY, 0);
            gl.Vertex(Global.printer.maxX, 0, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, 0, 0);
            gl.Vertex(Global.printer.maxX, 0, Global.printer.maxZ);
            gl.Vertex(0, 0, Global.printer.maxZ);
            gl.Vertex(0, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(0, Global.printer.maxY, 0);
            gl.Vertex(0, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(0, 0, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(0, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, 0, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, Global.printer.maxZ);
            gl.Vertex(Global.printer.maxX, Global.printer.maxY, 0);

            //模型切片后显示
            gl.Color(1.0f, 0.0f, 0.0f);
            foreach (var item in Global.printProject.model.layers)
            {
                List<Line3D> lines = item;
                for (int i = 0; i < lines.Count; i++)
                {
                    gl.Vertex(lines[i].start.X, lines[i].start.Y, lines[i].start.Z);
                    gl.Vertex(lines[i].end.X, lines[i].end.Y, lines[i].end.Z);
                }
            }

            gl.End();

            //原始模型显示
            gl.Begin(OpenGL.GL_TRIANGLES);
            foreach (var triangle in Global.printProject.model.triangles)
            {
                gl.Color(0.5f, 1.0f, 1.0f, 1.0f);
                gl.Vertex(triangle.p1.X, triangle.p1.Y, triangle.p1.Z);
                gl.Color(1.0f, 0.5f, 1.0f, 1.0f);
                gl.Vertex(triangle.p2.X, triangle.p2.Y, triangle.p2.Z);
                gl.Color(1.0f, 1.0f, 0.5f, 1.0f);
                gl.Vertex(triangle.p3.X, triangle.p3.Y, triangle.p3.Z);
            }
            gl.End();
            rotation2 += 1f;
        }
        #endregion

        /// <summary>
        /// 导入模型事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WindowImportModel(object sender, RoutedEventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog
            {
                Filter = "stl文件|*.stl|STL文件|*.STL"
            };
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                //Global.printProject = new Global.printProject();
                Global.printProject.model = new Model3D
                {
                    path = dialog.FileName
                };
                Utilities.ReadSTLFile(dialog.FileName, Global.printProject.model);
                //var ss = GeneratePrintPath(Global.printProject.model, (float)0.35);

                //string filePath = "printPath.txt";
                //using (StreamWriter writer = new StreamWriter(filePath))
                //{
                //    for (int i = 0; i < ss.Count; i++)
                //    {
                //        writer.WriteLine("Layer " + i + ":");
                //        foreach (Point3D point in ss[i])
                //        {
                //            writer.WriteLine(point.X + "," + point.Y + "," + point.Z);
                //        }
                //    }
                //}
            }
            Global.MainVM.flushProjectLabel();
        }
        public static Point3D RotatePoint(Point3D point, float angleX, float angleY, float angleZ)
        {
            // 将角度转换为弧度
            double radiansX = Math.PI * angleX / 180.0;
            double radiansY = Math.PI * angleY / 180.0;
            double radiansZ = Math.PI * angleZ / 180.0;

            // 绕Z轴旋转
            point = RotateZ(point, radiansZ);
            // 绕Y轴旋转
            point = RotateY(point, radiansY);
            // 绕X轴旋转
            point = RotateX(point, radiansX);

            return point;
        }

        private static Point3D RotateX(Point3D point, double radians)
        {
            double y = point.Y * Math.Cos(radians) - point.Z * Math.Sin(radians);
            double z = point.Y * Math.Sin(radians) + point.Z * Math.Cos(radians);
            return new Point3D(point.X, (float)y, (float)z);
        }

        private static Point3D RotateY(Point3D point, double radians)
        {
            double x = point.X * Math.Cos(radians) + point.Z * Math.Sin(radians);
            double z = -point.X * Math.Sin(radians) + point.Z * Math.Cos(radians);
            return new Point3D((float)x, point.Y, (float)z);
        }

        private static Point3D RotateZ(Point3D point, double radians)
        {
            double x = point.X * Math.Cos(radians) - point.Y * Math.Sin(radians);
            double y = point.X * Math.Sin(radians) + point.Y * Math.Cos(radians);
            return new Point3D((float)x, (float)y, point.Z);
        }
        public static void RotateModel(Model3D model, float angleX, float angleY, float angleZ)
        {
            foreach (var triangle in model.triangles)
            {
                triangle.p1 = RotatePoint(triangle.p1, angleX, angleY, angleZ);
                triangle.p2 = RotatePoint(triangle.p2, angleX, angleY, angleZ);
                triangle.p3 = RotatePoint(triangle.p3, angleX, angleY, angleZ);
            }
        }
        /// <summary>
        /// 切片事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WindowSliceCommand(object sender, RoutedEventArgs e)
        {
            if (Global.printProject.model.path == "")
            {
                System.Windows.MessageBox.Show("请先导入模型");
                return;
            }
            SliceParaView slice = new SliceParaView();
            slice.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            slice.SliceEvent += Event;
            slice.ShowDialog();
        }
        float planeHeight = 60;
        public void Event(float maxHeight, float minHeight, float precision, int fillMode, float fillInterval, int channel, int solidifyTime)
        {
            //分层
            Global.printProject.printLayers = new List<PrintLayer>();
            SliceContext sliceContext = new SliceContext(new IsothickSliceStrategy());
            int EmptyCount = 0;
            if (Global.SliceParaVM.FillModeSelectedIndex == 3)
            {
                Model3D model = Global.printProject.model;
                float layerHeight = maxHeight;
                // 生成打印路径
                List<List<Point3D>> printPath = GeneratePrintPath(model, layerHeight);

                // 将路径分配到 Global.printProject.printLayers
                Global.printProject.printLayers = new List<PrintLayer>();
                for (int i = 0; i < printPath.Count; i++)
                {
                    List<Point3D> layerPoints = printPath[i];

                    // 创建 PrintLayer 对象
                    PrintLayer printLayer = new PrintLayer
                    {
                        mode = 12 + fillMode, // 根据实际需求设置 mode
                        channel = channel,   // 根据实际需求设置 channel
                        interval = fillInterval, // 根据实际需求设置 interval
                        solidfyTime = solidifyTime, // 根据实际需求设置 solidfyTime
                        points = layerPoints,       // 设置路径点集
                        z_start = model.moveZ + i * layerHeight // 设置层的起始 Z 坐标
                    };

                    // 设置起始点
                    if (layerPoints.Count > 0)
                    {
                        printLayer.x_start = layerPoints[0].X;
                        printLayer.y_start = layerPoints[0].Y;
                        printLayer.z_start = layerPoints[0].Z;
                        Global.printProject.printLayers.Add(printLayer);// 添加到打印层列表
                    }
                    else
                        EmptyCount += 1;
                }
            }
            else
            {
                if (Global.SliceParaVM.SliceModeSelectedIndex == 0)
                    Global.printProject.model.layers = sliceContext.executeStrategy(Global.printProject.model, maxHeight, minHeight);
                else
                    Global.printProject.model.layers = sliceContext.executeStrategy1(Global.printProject.model, maxHeight, minHeight);
                Global.printProject.model.layers = Global.printProject.model.layers.Where(subList => subList.Count > 0).ToArray();
                //填充    
                FillContext fillContext = new FillContext(new SimpleFillStrategy());
                for (int i = 0; i < Global.printProject.model.layers.Length; i++)
                {
                    List<Point3D> tempPoints = Global.SliceParaVM.PrintModeSelectedIndex == 0
                        ? fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval, fillMode == 0 ? 1 : (fillMode == 4 ? 4 : (fillMode == 1 ? 0 : i % 2)))
                        : fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval);
                        //? fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval, fillMode == 0 ? 1 : (fillMode == 1 ? 0 : i % 2))
                        //? fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval, i % 2)
                    //tempPoints的Z  使用printLayer.height += float.Parse("0.1");
                    PrintLayer printLayer = new PrintLayer();//打印层
                    printLayer.points = tempPoints;
                    printLayer.mode = 10 + fillMode;
                    printLayer.channel = channel;
                    printLayer.interval = fillInterval;
                    printLayer.solidfyTime = solidifyTime;
                    //printLayer.height += i * 0.1f;
                    //Global.printProject.printLayers.Add(printLayer);
                    if (tempPoints.Count > 0)
                    {
                        printLayer.x_start = tempPoints[0].X;
                        printLayer.y_start = tempPoints[0].Y;
                        printLayer.z_start = tempPoints[0].Z;
                        Global.printProject.printLayers.Add(printLayer);
                    }
                    else
                        EmptyCount += 1;
                }
            }
            Global.MainVM.flushDgv();
            Global.SliceVM.TotalCount = "分层完成\r\n共" + (Global.printProject.printLayers.Count - EmptyCount) + "层，" + EmptyCount + "层为空";
        }
        private bool IsValidPoint(Point3D point)
        {
            return !float.IsNaN(point.X) &&
                   !float.IsNaN(point.Y) &&
                   !float.IsNaN(point.Z) &&
                   !float.IsInfinity(point.X) &&
                   !float.IsInfinity(point.Y) &&
                   !float.IsInfinity(point.Z);
        }
        public List<List<Point3D>> GeneratePrintPath(Model3D model, float layerHeight)
        {
            // 获取所有切片层的高度
            float minHeight = model.moveZ; // 模型最低点的Z坐标
            float maxHeight = model.modelHeight + model.moveZ; // 模型最高点的Z坐标
            int layerCount = (int)Math.Ceiling((maxHeight - minHeight) / layerHeight); // 切片层数

            List<List<Point3D>> printPath = new List<List<Point3D>>(layerCount);

            // 初始化每一层的路径列表
            for (int i = 0; i < layerCount; i++)
            {
                printPath.Add(new List<Point3D>());
            }
            // 遍历每个三角面片，计算与各切片层的交线，并将交线的点添加到对应层的路径中
            foreach (Triangle3D triangle in model.triangles)
            {
                for (int i = 0; i < layerCount; i++)
                {
                    float currentLayerHeight = minHeight + i * layerHeight;
                    if (currentLayerHeight >= triangle.minH && currentLayerHeight <= triangle.maxH)
                    {
                        // 计算三角面片与当前切片层的交线
                        List<Point3D> intersectionPoints = GetTriangleLayerIntersectionPoints(triangle, currentLayerHeight);

                        // 将交线的点添加到当前层的路径中
                        if (intersectionPoints.Count > 1)
                        {
                            // 确保路径是连续的
                            OptimizeLayerPath(intersectionPoints);
                            printPath[i].AddRange(intersectionPoints);
                        }
                    }
                }
            }

            // 对每一层的路径进行进一步优化
            for (int i = 0; i < printPath.Count; i++)
            {
                printPath[i] = MergePaths(printPath[i]);
            }

            // 遍历每个三角面片，计算与各切片层的交线，并将交线的点添加到对应层的路径中
            for (int i = 0; i < printPath.Count; i++)
            {
                // 先优化路径排序
                OptimizeLayerPath(printPath[i]);
                // 再合并路径
                printPath[i] = MergePaths(printPath[i]);

                // 添加闭合点（连接首尾）
                if (printPath[i].Count > 0)
                {
                    printPath[i].Add(printPath[i][0]);
                }
            }

            return printPath;
        }

        private List<Point3D> GetTriangleLayerIntersectionPoints(Triangle3D triangle, float layerHeight)
        {
            List<Point3D> intersectionPoints = new List<Point3D>();

            // 检查三角面片的每条边与切片层的交点
            CheckEdgeIntersection(triangle.p1, triangle.p2, layerHeight, intersectionPoints);
            CheckEdgeIntersection(triangle.p2, triangle.p3, layerHeight, intersectionPoints);
            CheckEdgeIntersection(triangle.p3, triangle.p1, layerHeight, intersectionPoints);

            return intersectionPoints;
        }

        private void CheckEdgeIntersection(Point3D p1, Point3D p2, float layerHeight, List<Point3D> intersectionPoints)
        {
            const float epsilon = 1e-6f;  // 浮点精度容差

            // 处理线段完全在切层上的情况
            if (Math.Abs(p1.Z - layerHeight) < epsilon &&
                Math.Abs(p2.Z - layerHeight) < epsilon)
            {
                intersectionPoints.Add(p1);
                intersectionPoints.Add(p2);
                return;
            }

            // 检查线段是否跨越切层
            bool crossesLayer = (p1.Z <= layerHeight + epsilon && p2.Z >= layerHeight - epsilon) ||
                               (p2.Z <= layerHeight + epsilon && p1.Z >= layerHeight - epsilon);

            if (!crossesLayer) return;

            float denominator = p2.Z - p1.Z;

            // 处理垂直方向平行的情况
            if (Math.Abs(denominator) < epsilon)
            {
                // 线段与切层平行但不在切层上时跳过
                return;
            }

            float t = (layerHeight - p1.Z) / denominator;
            t = Math.Max(0, Math.Min(1, t));  // 钳制t在[0,1]范围内

            Point3D intersection = new Point3D(
                p1.X + t * (p2.X - p1.X),
                p1.Y + t * (p2.Y - p1.Y),
                layerHeight
            );

            // 有效性检查
            if (IsValidPoint(intersection))
            {
                intersectionPoints.Add(intersection);
            }
        }

        private void OptimizeLayerPath(List<Point3D> layerPath)
        {
            if (layerPath.Count == 0) return;

            // 计算几何中心
            float centerX = (float)layerPath.Average(p => p.X);
            float centerY = (float)layerPath.Average(p => p.Y);

            // 按极角排序
            layerPath.Sort((a, b) =>
                Math.Atan2(a.Y - centerY, a.X - centerX).CompareTo(
                Math.Atan2(b.Y - centerY, b.X - centerX)));
        }
        private List<Point3D> MergePaths(List<Point3D> paths)
        {
            if (paths.Count == 0) return new List<Point3D>();

            // 使用极角排序代替贪心算法
            float centerX = (float)paths.Average(p => p.X);
            float centerY = (float)paths.Average(p => p.Y);

            return paths
                .OrderBy(p => Math.Atan2(p.Y - centerY, p.X - centerX))
                .ToList();
        }
        //public void Event(float maxHeight, float minHeight, float precision, int fillMode, float fillInterval, int channel, int solidifyTime)
        //{
        //    //分层
        //    Global.printProject.printLayers = new List<PrintLayer>();
        //    SliceContext sliceContext = new SliceContext(new IsothickSliceStrategy());
        //    Global.printProject.model.layers = sliceContext.executeStrategy(Global.printProject.model, maxHeight, minHeight);
        //    Global.printProject.model.layers = Global.printProject.model.layers.Where(subList => subList.Count > 0).ToArray();
        //    for (int i = 0; i < Global.printProject.model.layers.Count(); i++)
        //    {
        //        // 提取当前层的所有点
        //        List<Point3D> extractedPoints = Utilities.ExtractPointsFromLayer(Global.printProject.model.layers[i]);

        //        // 转置和排序点
        //        //List<Point3D> processedPoints = Utilities.RotateAndSortPoints(extractedPoints);

        //        // 旋转点90度
        //        List<Point3D> rotatedPoints = Utilities.RotatePoints90Degrees(extractedPoints);

        //        // 将转置和排序后的点集映射回当前层
        //        Global.printProject.model.layers[i] = Utilities.CreateLinesFromPoints(rotatedPoints);
        //    }
        //    //填充    
        //    FillContext fillContext = new FillContext(new SimpleFillStrategy());
        //    int EmptyCount = 0;
        //    for (int i = 0; i < Global.printProject.model.layers.Length; i++)
        //    {
        //        List<Point3D> tempPoints = Global.SliceParaVM.PrintModeSelectedIndex == 0
        //            ? fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval, i % 2)
        //            : fillContext.executeStrategy(Global.printProject.model.layers[i], fillInterval);
        //        //tempPoints的Z  使用printLayer.height += float.Parse("0.1");
        //        PrintLayer printLayer = new PrintLayer();//打印层
        //        printLayer.points = tempPoints;
        //        printLayer.mode = 10 + fillMode;
        //        printLayer.channel = channel;
        //        printLayer.interval = fillInterval;
        //        printLayer.solidfyTime = solidifyTime;
        //        //printLayer.height += i * 0.1f;
        //        //Global.printProject.printLayers.Add(printLayer);
        //        if (tempPoints.Count > 0)
        //        {
        //            printLayer.x_start = tempPoints[0].X;
        //            printLayer.y_start = tempPoints[0].Y;
        //            printLayer.z_start = tempPoints[0].Z;
        //            Global.printProject.printLayers.Add(printLayer);
        //        }
        //        else
        //            EmptyCount += 1;
        //    }
        //    Global.MainVM.flushDgv();
        //    Global.SliceVM.TotalCount = "分层完成\r\n共" + (Global.printProject.printLayers.Count - EmptyCount) + "层，" + EmptyCount + "层为空";
        //}


        private string GetPrintModeString(int mode)
        {
            switch (mode)
            {
                case 0: return "蛇形";
                case 1: return "回形";
                case 2: return "网格形";
                case 10: return "纵向填充";
                case 11: return "横向填充";
                case 12: return "横向纵横交替填充";
                default: return "未知";
            }
        }

        private void btnModifyModel_Click(object sender, RoutedEventArgs e)
        {
            //RotateModel(Global.printProject.model, 0, -45, 0);
            VM.ModifyModel();
        }

        private void cmbModel_DropDownOpened(object sender, EventArgs e)
        {
            try
            {
                string path = System.IO.Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
                         + System.IO.Path.DirectorySeparatorChar.ToString();
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                // 获取目录下的所有STL文件
                string[] stlFiles = Directory.GetFiles(path, "*.stl");

                // 清空ModelList并添加新的文件名
                Global.CurrentProjectVM.ModelList.Clear();
                foreach (var file in stlFiles)
                {
                    string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(file);
                    Global.CurrentProjectVM.ModelList.Add(fileNameWithoutExtension);
                }
            }
            catch (Exception ex)
            {
                Global.LogHelper.WriteLog("Open Files Error:" + ex.Message);
            }
        }

        private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.FontSize = e.NewSize.Width / 85;
        }
    }
}
